package utils

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/bytedance/sonic"
	"io"
	"mime/multipart"
	"net/http"
	"net/url"
	"strings"
)

const UrlPrefix = "https://storebms.supore.cn"

var AuthToken string

type HttpRequestOptions struct {
	Method      string
	Suffix      string
	Headers     map[string]string
	QueryParams map[string]interface{}
	Body        map[string]interface{}
	FormData    url.Values
	Resp        interface{}
	Prefix      string
}

type JsResp struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
}

func HttpRequest(options HttpRequestOptions) error {
	if options.Resp == nil {
		return fmt.Errorf("dst must not be nil")
	}
	u, err := url.Parse(options.Suffix)
	if err != nil {
		return fmt.Errorf("invalid URL: %w", err)
	}
	// Add query parameters if any
	if len(options.QueryParams) > 0 {
		q := u.Query()
		for key, value := range options.QueryParams {
			q.Add(key, fmt.Sprintf("%v", value))
		}
		u.RawQuery = q.Encode()
	}
	var body io.Reader
	var contentType string
	// Handle different types of request bodies
	if options.Body != nil {
		jsonData, err := json.Marshal(options.Body)
		if err != nil {
			return fmt.Errorf("error marshaling payload: %w", err)
		}
		body = bytes.NewBuffer(jsonData)
		contentType = "application/json"
	} else if options.FormData != nil {
		body = strings.NewReader(options.FormData.Encode())
		contentType = "application/x-www-form-urlencoded"
	}
	dstUrl := ""
	if options.Prefix != "" {
		dstUrl = fmt.Sprintf("%s%s", options.Prefix, u.String())
	} else {
		dstUrl = fmt.Sprintf("%s%s", UrlPrefix, u.String())
	}
	req, err := http.NewRequest(options.Method, dstUrl, body)
	if err != nil {
		return fmt.Errorf("error creating request: %w", err)
	}
	//if options.Headers == nil {
	//	options.Headers = make(map[string]string)
	//}
	//options.Headers = make(map[string]string)
	defaultHeaders := map[string]string{
		"Accept":          "application/json, text/plain, */*",
		"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5,ja;q=0.4",
		"Cache-Control":   "no-cache",
		"Connection":      "keep-alive",
		"Pragma":          "no-cache",
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
	}
	if AuthToken != "" {
		defaultHeaders["x-token"] = AuthToken
	}
	// Set content type if we have a body
	if body != nil && defaultHeaders["Content-Type"] == "" {
		defaultHeaders["Content-Type"] = contentType
	}
	// Set all headers
	for key, value := range defaultHeaders {
		req.Header.Set(key, value)
	}
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error making request: %w", err)
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error reading response body: %w", err)
	}
	if resp.StatusCode >= 400 {
		//AuthToken = "" //授权过期
		return fmt.Errorf("request failed with status %d: %s", resp.StatusCode, resp.Status)
	}

	err = json.Unmarshal(responseBody, options.Resp)
	if err != nil {
		return fmt.Errorf("error unmarshalling response: %w", err)
	}

	//if jsResp, ok := options.Resp.(*JsResp); ok {
	//	if jsResp.Code != 0 {
	//		return fmt.Errorf("request failed with code %d: %s", jsResp.Code, jsResp.Msg)
	//	}
	//} else {
	//	return fmt.Errorf("unexpected response type: %T", options.Resp)
	//}
	return nil
}

func HttpUploadRequest(fileBytes []byte, res interface{}) error {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	// 创建文件字段
	part, err := writer.CreateFormFile("file", "file.png")
	if err != nil {
		return fmt.Errorf("error creating form file: %w", err)
	}

	// 写入文件内容
	_, err = part.Write(fileBytes)
	if err != nil {
		return fmt.Errorf("error writing file content: %w", err)
	}

	// 关闭writer以完成表单构建
	err = writer.Close()
	if err != nil {
		return fmt.Errorf("error closing writer: %w", err)
	}

	defaultHeaders := map[string]string{
		"Accept":          "application/json, text/plain, */*",
		"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5,ja;q=0.4",
		"Cache-Control":   "no-cache",
		"Connection":      "keep-alive",
		"Pragma":          "no-cache",
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
	}

	dstUrl := fmt.Sprintf("%s%s", UrlPrefix, "/upload")
	req, err := http.NewRequest("POST", dstUrl, body)
	if err != nil {
		return fmt.Errorf("error creating request: %w", err)
	}

	// 设置正确的 Content-Type 头，包含 boundary
	req.Header.Set("Content-Type", writer.FormDataContentType())

	// 设置其他头部
	for key, value := range defaultHeaders {
		req.Header.Set(key, value)
	}

	// 设置认证令牌（修复：应该设置到 req.Header 而不是 defaultHeaders）
	if AuthToken != "" {
		req.Header.Set("x-token", AuthToken)
	}

	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error making request: %w", err)
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error reading response body: %w", err)
	}

	if resp.StatusCode >= 400 {
		return fmt.Errorf("request failed with status %d: %s, body: %s", resp.StatusCode, resp.Status, string(responseBody))
	}

	err = json.Unmarshal(responseBody, res)
	if err != nil {
		return fmt.Errorf("error unmarshalling response: %w", err)
	}

	return nil
}

func HttpLocalRequest(options HttpRequestOptions) error {
	if options.Resp == nil {
		return fmt.Errorf("dst must not be nil")
	}
	u, err := url.Parse(options.Suffix)
	if err != nil {
		return fmt.Errorf("invalid URL: %w", err)
	}
	if len(options.QueryParams) > 0 {
		q := u.Query()
		for key, value := range options.QueryParams {
			q.Add(key, fmt.Sprintf("%v", value))
		}
		u.RawQuery = q.Encode()
	}
	var body io.Reader
	var contentType string
	if options.Body != nil {
		jsonData, err := json.Marshal(options.Body)
		if err != nil {
			return fmt.Errorf("error marshaling payload: %w", err)
		}
		body = bytes.NewBuffer(jsonData)
		contentType = "application/json"
	} else if options.FormData != nil {
		body = strings.NewReader(options.FormData.Encode())
		contentType = "application/x-www-form-urlencoded"
	}
	defaultHeaders := map[string]string{
		"Accept":          "application/json, text/plain, */*",
		"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,zh-TW;q=0.5,ja;q=0.4",
		"Cache-Control":   "no-cache",
		"Connection":      "keep-alive",
		"Pragma":          "no-cache",
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
	}
	if body != nil && defaultHeaders["Content-Type"] == "" {
		defaultHeaders["Content-Type"] = contentType
	}
	dstUrl := fmt.Sprintf("%s%s", "http://127.0.0.1:8001", u.String())
	req, err := http.NewRequest(options.Method, dstUrl, body)
	for key, value := range defaultHeaders {
		req.Header.Set(key, value)
	}
	if err != nil {
		return fmt.Errorf("error creating request: %w", err)
	}
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("error making request: %w", err)
	}
	defer resp.Body.Close()
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("error reading response body: %w", err)
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("request failed with status %d: %s", resp.StatusCode, resp.Status)
	}
	err = sonic.Unmarshal(responseBody, options.Resp)
	if err != nil {
		return fmt.Errorf("error unmarshalling response: %w", err)
	}
	return nil
}
